// LocationStatusService.java
package com.mytech.cslive.services;

import com.mytech.cslive.infrastructure.LogFile;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class LocationStatusService extends Service {
	private static final int UPDATE_LOCATION_INTERVAL_MS = 500;
	private static final int UPDATE_LOCATION_DISTANCE_CHANGE = 1;
	private static boolean isServiceOn = false;
	
	private String provider;

	private LocationManager locationManager;
	private Messenger messenger;

	public final static String TAG = "CSLIVE/LocationStatusService";
	public static final String EXTRA_MESSENGER = "com.mytech.cslive.LocationStatusService.EXTRA_MESSENGER";
	public static final String LOCATION_KEY = "LOCATION_KEY";

	@Override
	public void onCreate() {
		super.onCreate();
		gpsSetup();
	}

	@Override
	public void onDestroy() {
		Log.d(TAG, "Location status service stopped");
		
		// Stop trying to discern locations
		stopLocationUpdates();
		setServiceOn(false);
		
		super.onDestroy();
	}

	public static int getUpdateLocationDistanceChange() {
		return UPDATE_LOCATION_DISTANCE_CHANGE;
	}
	
	public static int getUpdateLocationIntervalMs() {
		return UPDATE_LOCATION_INTERVAL_MS;
	}

	public static boolean isServiceOn() {
		return isServiceOn;
	}

	public static void setServiceOn(boolean isServiceOn) {
		LocationStatusService.isServiceOn = isServiceOn;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(TAG, "service started\n DATA:\n" + locationManager.toString()
				+ "\n" + provider + "\n");
		
		// Only if the service isn't already on
		if (!isServiceOn()) {
			setServiceOn(true);
			
			// Get initial location
			locationManager.getLastKnownLocation(provider);
			
			// Request location updates
			locationManager.requestLocationUpdates(provider,
					getUpdateLocationIntervalMs(),
					getUpdateLocationDistanceChange(), locationListener);
	
			Bundle extras = intent.getExtras();
	
			if (extras != null) {
				setMessenger((Messenger) extras.get(EXTRA_MESSENGER));
			} else {
				Error e = new Error("No additional handler for: " + TAG
						+ ", something is wrong, exiting");
				throw e;
			}
		}

		return Service.START_STICKY;
	}

	private void gpsSetup() {
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);
		provider = locationManager.getBestProvider(criteria, true);
	}
	
	/**
	 * Stop using updating locationListener
	 */
	public void stopLocationUpdates() {
		if (locationManager != null) {
			locationManager.removeUpdates(locationListener);
			setServiceOn(false);
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	private Messenger getMessenger() {
		return messenger;
	}

	private void setMessenger(Messenger messenger) {
		this.messenger = messenger;
	}

	private final LocationListener locationListener = new LocationListener() {
		private void sendMsgToHandler(Location location) throws RemoteException {
			if (location != null) {
				Bundle msgBundle = new Bundle();
				msgBundle.putParcelable(LOCATION_KEY, location);
				Message msg = Message.obtain();
				msg.setData(msgBundle);
				getMessenger().send(msg);

			} else {
				Log.d(TAG, "Location is currently null");
			}
		}

		@Override
		public void onLocationChanged(Location location) {
			try {
				sendMsgToHandler(location);
			} catch (RemoteException e) {
				LogFile.log(e);
				// player fatal exception
				e.printStackTrace();
			}
		}

		@Override
		public void onProviderDisabled(String provider) {
			// Maybe need to insert exception, or inside the next method
			try {
				sendMsgToHandler(null);
			} catch (RemoteException e) {
				LogFile.log(e);
				// player fatal exception
				e.printStackTrace();
			}

		}

		@Override
		public void onProviderEnabled(String provider) {
			// Currently empty
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// Currently empty
		}
	};

}